import Vue from 'vue';


class Store {
    constructor(options) {

        // 解决state的响应式
        this.vm = new Vue({
            data: {
                state: options.state
            }
        })

        // 实现getters
        let getters = options.getter || {}
        this.getters = {}
        Object.keys(getters).forEach(getterName => {
            Object.defineProperty(this.getters, getterName, {
                get: () => {
                    return getters[getterName](this.state)
                }
            })
        })

        // 实现mutations
        let mutations = options.mutations || {}
        this.mutations = {}
        Object.keys(mutations).forEach(mutationName => {
            this.mutations[mutationName] = (arg) => {
                mutations[mutationName](this.state, arg)
            }
        })

        //实现actions
        let actions = options.actions
        this.actions = {}
        Object.keys(actions).forEach(actionName => {
            this.actions[actionName] = (arg) => {
                actions[actionName](this, arg)
            }
        })

    }

    //commit
    commit = (method, arg) => {
        this.mutations[method](arg)
    }

    // dispatch
    dispatch = (method, arg) => {
        this.actions[method](arg)
    }

    //新增代码
    get state() {
        return this.vm.state
    }
}

/**
 * 五、完善install
 * 1.参数Vue，Vue.use执行install的时候，会将Vue作为参数传进来
 * 2.mixin的作用时将mixin的内容混合到Vue的初始参数options中
 * 3.为什么是beforeCreate而不是created呢？因为如果是在created操作的话，$options已经初始化好了
 * 4.判断如果当前是根组件的话，就将传入的store挂载到根组件的实例上，属性名称为 $store
 * 5.如果当前是子组件的话，就将根组件的 $stroe 也赋值给子组件，则每一个组件都拥有同一个 $store
 * */
let install = function (Vue) {
    Vue.mixin({
        beforeCreate() {
            if (this.$options && this.$options.store) { // 如果是根组件
                this.$store = this.$options.store
            } else {
                this.$store = this.$parent && this.$parent.$store
            }
        }
    })
}

let Vuex = {
    Store,
    install
}

export default Vuex